package logger

import (
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"go-gin-init/app/core"
	"os"
	"path"
)

// 颜色
const (
	red    = 31
	yellow = 33
	blue   = 36
	gray   = 37
)

type LogFormatter struct {
	mode string
}

// Format 实现Formatter(entry *logrus.Entry) ([]byte, error)接口
func (t *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) {

	var b *bytes.Buffer
	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = &bytes.Buffer{}
	}

	timestamp := entry.Time.Format("2006-01-02 15:04:05")

	var funcVal string
	var fileVal string
	if entry.HasCaller() {
		//自定义文件路径
		funcVal = entry.Caller.Function
		fileVal = fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
	}

	var levelColor int
	level := entry.Level
	//根据不同的level去展示颜色
	if t.mode == "info" {
		switch level {
		case logrus.DebugLevel, logrus.TraceLevel:
			levelColor = gray
		case logrus.WarnLevel:
			levelColor = yellow
		case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
			levelColor = red
		default:
			levelColor = blue
		}

		if !entry.HasCaller() {
			fmt.Fprintf(b, "[%s] \x1b[%dm[%s]\x1b[0m %s\n", timestamp, levelColor, entry.Level, entry.Message)
		}
		// dev 带颜色输出
		fmt.Fprintf(b, "[gin-init]%s \x1b[%dm[%s]\x1b[0m %s %s\n", timestamp, levelColor, entry.Level, fileVal, entry.Message)

	} else {
		// pro 日志文件输出
		fmt.Fprintf(b, "[gin-init]%s	%s		%s	[%s]		%s\n", timestamp, level, fileVal, funcVal, entry.Message)
	}

	return b.Bytes(), nil
}

type MyHook struct {
	errFile  *os.File
	warnFile *os.File
	level    string
}

// 设置一个field
func (hook *MyHook) Fire(entry *logrus.Entry) error {

	// 只有在生产环境下才进行日志文件写入
	if hook.level == "dev" {
		return nil
	}
	line, _ := entry.String()
	switch entry.Level {
	case logrus.ErrorLevel:
		hook.errFile.Write([]byte(line))
	case logrus.WarnLevel:
		hook.warnFile.Write([]byte(line))
	}

	return nil
}

// 哪些等级的日志才会生效
func (hook *MyHook) Levels() []logrus.Level {
	return []logrus.Level{logrus.ErrorLevel, logrus.WarnLevel}
}

func InitLogrus() {

	logConf := core.Conf.LogrusLog

	level := core.Conf.Server.Mode

	logrus.SetReportCaller(true)
	// 日志级别
	logrusLevel, err := logrus.ParseLevel(level)
	if err != nil {
		fmt.Println(err)
		panic("logrus 日志级别配置level错误")
	}
	logrus.SetLevel(logrusLevel)
	// 自定义日志格式
	logrus.SetFormatter(&LogFormatter{mode: level})

	//  对于开发环境，直接打印颜色日志在终端 ，
	// 	对于生产环境，则直接用钩子函数写入日志文件
	// 	为什么生产环境不进行日志文件输出与终端一起输出，因为dev是带颜色输出，输入进文件将会对于颜色有乱码
	if level == "info" {
		logrus.SetOutput(os.Stdout)
		logrus.Info("日志初始化完成")
		return
	}

	// 使用钩子函数来进行文件保存
	// 文件保存路径
	errFile, err := os.OpenFile(logConf.ErrLogPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)

	warnFile, err := os.OpenFile(logConf.WarnLogPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)

	if err != nil {
		fmt.Println(err)
		panic("logrus日志初始化失败")
	}

	Hook := MyHook{errFile, warnFile, level}

	logrus.AddHook(&Hook)

	//	writers := []io.Writer{
	//		os.Stdout,
	//		allFile}
	//	fileAndStdoutWriter := io.MultiWriter(writers...)
	//	logrus.SetOutput(fileAndStdoutWriter)

	logrus.Info("日志初始化完成")

}
